use crate::errors::MyError;
use crate::models::{DeleteNoteQuery, GetNoteQuery, Note, NoteCategory, NoteProfile, Res};
use crate::services;
// use crate::services::{delete_note, get_note, get_notes, insert_or_update_note};
use actix_web::{delete, get, post, web, HttpRequest};
use deadpool_postgres::{Client, Pool};
use std::result::Result;

fn get_user_id(req: &HttpRequest) -> Result<String, MyError> {
    let user_id = req
        .headers()
        .get("user-id")
        .ok_or_else(|| MyError::Msg("user-id not set in header".to_string()))?;
    let result = user_id
        .to_str()
        .map_err(|e| MyError::Msg(format!("get_user_id/to_str error:{}", e)))?
        .to_string();
    if result.is_empty() {
        return Err(MyError::Msg("user-id为空".to_string()));
    }
    Ok(result)
}
#[post("/notes")]
pub async fn post_notes(
    req: HttpRequest,
    note: web::Json<Note>,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<u32>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    Ok(web::Json(Res::new(
        services::insert_or_update_note(&note.into_inner(), &client, &get_user_id(&req)?).await?,
    )))
}
#[get("/notes")]
pub async fn get_notes(
    req: HttpRequest,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<Vec<Note>>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    Ok(web::Json(Res::new(
        services::get_notes(&client, &get_user_id(&req)?).await?,
    )))
}
#[get("/notes")]
pub async fn get_note(
    req: HttpRequest,
    query: web::Query<GetNoteQuery>,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<Note>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    Ok(web::Json(Res::new(
        services::get_note(query.id, &client, &get_user_id(&req)?).await?,
    )))
}
#[delete("/notes")]
pub async fn delete_note(
    req: HttpRequest,
    query: web::Query<DeleteNoteQuery>,
    pg_pool: web::Data<Pool>,
) -> Result<&'static str, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    services::delete_note(query.id, &client, &get_user_id(&req)?).await?;
    Ok("")
}
//note_profiles
#[get("/note_profiles")]
pub async fn note_profiles(
    req: HttpRequest,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<Vec<NoteProfile>>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    Ok(web::Json(Res::new(
        services::get_note_profiles(&client, &get_user_id(&req)?).await?,
    )))
}

//#[post("/api/note_categories", format = "json", data = "<note_category>")]
#[post("/api/note_categories")]
pub async fn post_note_categories(
    note_category: web::Json<NoteCategory>,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<String>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    Ok(web::Json(Res::new(
        services::insert_or_update_note_category(&note_category.into_inner(), &client).await?,
    )))
}

#[delete("/api/note_categories/{id}")]
pub async fn delete_note_note_category(
    path: web::Path<String>,
    pg_pool: web::Data<Pool>,
) -> Result<&'static str, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    let id = path.into_inner();
    services::delete_category(&id, &client).await?;
    Ok("")
}

#[get("/api/note_category/{id}")]
pub async fn get_note_category(
    path: web::Path<String>,
    pg_pool: web::Data<Pool>,
) -> Result<web::Json<Res<NoteCategory>>, MyError> {
    let client: Client = pg_pool.get().await.map_err(MyError::PoolError)?;
    let id = path.into_inner();
    Ok(web::Json(Res::new(
        services::get_category_with_children(&id, &client).await?,
    )))
}
